package com.zhj.config;

import com.zhj.filter.CaptchaCodeFilter;
import com.zhj.po.MyUserDetailsService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.Resource;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
   @Resource
   private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;
   @Resource
   private MyUserDetailsService  userDetailsService;
   @Resource
   private MyAuthenticationFailureHandler myAuthenticationFailureHandler;
   @Resource
   MyLogoutSuccessHandler myLogoutSuccessHandler;
   @Resource
   private CaptchaCodeFilter captchaCodeFilter;
   @Resource
   private SmsCodeSecurityConfig smsCodeSecurityConfig;
   @Override
   protected void configure(HttpSecurity http) throws Exception {
      http.csrf().disable() //禁用跨站csrf攻击防御，后面的章节会专门讲解
              .addFilterBefore(captchaCodeFilter, UsernamePasswordAuthenticationFilter.class)
              .logout()
              .logoutUrl("/signout")
              .deleteCookies("JSESSIONID")
              .logoutSuccessHandler(myLogoutSuccessHandler)
              //.logoutUrl("/aftersignout")
              .and()
              .formLogin()
              .loginPage("/login.html")
              .loginProcessingUrl("/login")
              .successHandler(myAuthenticationSuccessHandler)
              .failureHandler(myAuthenticationFailureHandler)
              .and().rememberMe()
               .rememberMeParameter("remember-me-new")
              .rememberMeCookieName("remember-me-cookie")
              .tokenValiditySeconds(2 * 24 * 60 * 60)
              .and().apply(smsCodeSecurityConfig)
              .and()
              .authorizeRequests()
              .antMatchers("/login.html","/login","/index1","/kaptcha","/signout","/smscode","/testP","/testRedis").permitAll()//不需要通过登录验证就可以被访问的资源路径
              .anyRequest().access("@rabcService.hasPermission(request,authentication)")
              /*.antMatchers("/biz1","/biz2") //需要对外暴露的资源路径
              .hasAnyAuthority("ROLE_user","ROLE_admin")  //user角色和admin角色都可以访问
              .antMatchers("/sys_log1").hasAuthority("/sys_log1")
              .antMatchers("/sys_user1").hasAuthority("/sys_user1")
              .antMatchers("/biz1").hasAuthority("/biz1")
              .antMatchers("/biz2").hasAuthority("/biz2")
              .anyRequest().
              authenticated()*/
               .and().sessionManagement().  //设置session创建的策略
              sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
               .invalidSessionUrl("/login.html")
              .maximumSessions(1)
               .maxSessionsPreventsLogin(false)
               .expiredSessionStrategy(new UserLogoutHandler())
      ;
   }
   @Override
   public void configure(AuthenticationManagerBuilder auth) throws Exception {
      auth.userDetailsService(userDetailsService)
              .passwordEncoder(passwordEncoder());
   }

   @Bean
   public PasswordEncoder passwordEncoder(){
      return new BCryptPasswordEncoder();
   }
   @Override
   public void configure(WebSecurity web) {
      //将项目中静态资源路径开放出来
      web.ignoring().antMatchers( "/css/**", "/fonts/**", "/img/**", "/js/**");
   }

}